#ifndef __SMS_PARAMETER__
#define __SMS_PARAMETER__

#include "sms_helper.h"
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <thread>
#include <mutex>
#include <queue>
#include <condition_variable>


namespace sms {


class Parameter
{

public:
    Parameter(
        std::string node_name,
        std::function<void(nlohmann::json)> callable,
        std::string ip="127.0.0.1",
        int port=9094,
        bool request_once=false
    );
    ~Parameter();
    void kill();
    void recv_loop();
    void heartbeat_loop();
    void join();
    void set_params(nlohmann::json params);
    void set_param(std::string param_name, nlohmann::json value);
    nlohmann::json get_params_remote(std::vector<std::string> keys);
    nlohmann::json get_param(std::string param_name, nlohmann::json default_=0.0);

public:
    nlohmann::json sync_params;

private:
    bool _link();
    void _heartbeat();
    void _close_socket();
    void _parse_msg(std::string msg);

    std::string _node_name;
    std::function<void(nlohmann::json)> _callable;
    std::string _ip;
    int _port;
    bool _request_once;
    std::mutex _send_mtx;
    std::mutex _queue_mtx;
    std::queue<nlohmann::json> _recv_queue;
    std::condition_variable _cv;

    double _last_send_time;
    bool _force_quit;
    bool _heartbeat_running;
    bool _running;

    int _client_socket;
    struct sockaddr_in _server_addr;
    char* _buf;

    std::string _last_msg;
    int _last_msg_len;

    std::thread* _recv_t;
    std::thread* _heartbeat_t;
};


}

#endif
